{# Form macros. Native inputs with ``name`` attributes, so every form posts or re-queries through htmx without client-side state. {% from "components/macros/form.html" import field, text_input, select, date_input, primary_button %} #} {%- set _primary_button_classes -%} text-sm text-aegis-text border border-aegis-teal bg-aegis-teal/10 rounded px-4 py-2.5 hover:bg-aegis-teal/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center gap-2 {%- endset -%} {# Inline primary button (no loading spinner). Defaults to ``type="button"`` so it doesn't accidentally submit a form it's nested inside — pass ``type="submit"`` explicitly when you want submit semantics. ``attrs`` lets the caller pass arbitrary attributes (Alpine ``@click``, ``:disabled``, ``aria-*``) without bloating the macro signature. #} {% macro primary_button(label, type="button", attrs="") %} {% endmacro %} {# Primary submit button with an inline loading spinner. Parent scope must expose ``loading`` (bool) — typically flipped by ``@submit="loading = true"`` on the form. The button disables itself while loading so a double-click can't double-submit. #} {% macro submit_button(idle_label, loading_label) %} {% endmacro %} {# Shared input styling; every control below uses it so the bar reads as one. #} {%- set _control_classes -%} bg-aegis-bg border border-aegis-border rounded px-2.5 py-1.5 text-sm text-aegis-text placeholder:text-aegis-muted/50 focus:border-aegis-teal focus:outline-none transition-colors {%- endset -%} {# A native select. ``options`` are objects or dicts with ``id`` and ``name``; ``blank`` is the "no filter" label (``None`` for no blank choice); ``selected`` the current id. ``label`` wraps it inline for a filter bar; ``block`` lays it out full-width inside a ``field()``. #} {% macro select(name, options, selected=None, blank="All", label=None, block=False) %} {% if label %}{% endif %} {% endmacro %} {% macro date_input(name, value=None, label=None, block=False) %} {% if label %}{% endif %} {% endmacro %} {% macro checkbox(name, checked=False, label=None) %} {% endmacro %} {% macro search_input(name, value=None, placeholder="Search") %} {% endmacro %} {# A labelled field. The control comes via {% call %}; ``error`` renders under it (pattern 1's 422 re-render passes field errors here). #} {% macro field(label, error=None) %}
{% if error %}

{{ error }}

{% endif %}
{% endmacro %} {% macro text_input(name, value=None, placeholder="", required=False, autofocus=False) %} {% endmacro %} {% macro money_input(name, value=None, placeholder="0.00") %}
{% endmacro %} {% macro textarea(name, value=None, rows=6, placeholder="") %} {% endmacro %} {# Themed combobox — replaces native {% endmacro %} {# "OR" divider with hairlines — sits between a form and an alternate action (e.g. email/password above, OAuth buttons below). #} {% macro or_divider() %}
or
{% endmacro %} {# The time-window chips: a row of exclusive pills that submits as one radio field, so a click re-requests the enclosing form. Same recipe as ``layout.chip``, driven by ``peer-checked`` because a radio rather than a link marks the choice. #} {% macro range_chips(ranges, days, field="days", aria="Time window") %}
{% for value, label in ranges %} {% endfor %}
{% endmacro %} {# A small action button (row verbs, card verbs, toolbar). ``attrs`` is the htmx verb; ``vals`` a dict for ``hx-vals``; ``tone`` is default (quiet), primary (teal), danger or warn. The one recipe every compact button uses. #} {% macro action(label, attrs, tone="default", vals=None) %} {% set tones = {"default": "border-aegis-border text-aegis-muted hover:text-aegis-text hover:border-aegis-muted", "primary": "border-aegis-teal text-aegis-text hover:bg-aegis-teal/10", "danger": "border-aegis-error/40 text-error hover:border-aegis-error", "warn": "border-aegis-amber/40 text-aegis-text hover:border-aegis-amber"} %} {% endmacro %}